import { normalize, optimize, parse, procToC, procToString, procToWasm } from './purs'
import BfWorker from './worker?worker&inline'

export type Output = {
  ir: string
  c: string
  wasm: Promise<WebAssembly.Module>
}

export const compile = (src: string, opt: boolean): string | Output => {
  let proc = parse(src)
  if (typeof proc != 'string') {
    if (opt) proc = normalize(optimize(proc))
    return {
      ir: procToString(proc),
      c: procToC(proc),
      wasm: WebAssembly.compile(procToWasm(proc)),
    }
  }
  return proc
}

/**
 * 返回用于取消的函数
 */
export const runBf = (
  mod: WebAssembly.Module,
  input: number[],
  pos: number,
  mem: number,
  onOut: (output: string) => void,
  onEnd: () => void,
  onErr: (msg: string) => void,
) => {
  let output = ''

  const worker = new BfWorker()

  worker.onmessage = ({ data }) => ({
    end() {
      onEnd()
    },
    err() {
      onErr(data.msg)
    },
    out() {
      output += String.fromCharCode(data.code)
      onOut(output)
    },
  })[data.type as string]!()

  worker.postMessage({ mod, input, pos, mem })

  return () => worker.terminate()
}